package com.ag.utils;

import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.Assert;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.TypeUtils;

/**
 * 请使用 Jsons 类
 *
 * @author rplees
 * @email rplees.i.ly@gmail.com
 * @version 1.0  
 * @created Mar 17, 2021 1:58:54 PM
 */
public class JsonUtils {
	public static JSONObject formObject(Object o) {
		if(o != null && o instanceof String) {
			if(StringUtils.isBlank(o.toString())) return null;
			return JSON.parseObject(o.toString());
		}
		return JSON.parseObject(JSON.toJSONString(o));
	}
	
	public static JSONObject formObject(Object o, SerializerFeature... features) {
		if(o != null && o instanceof String) {
			if(StringUtils.isBlank(o.toString())) return null;
			return JSON.parseObject(o.toString());
		}
		return JSON.parseObject(JSON.toJSONString(o, features));
	}
	
	/**
	 * 封装一个列表到树形结构的JSONArray
	 * @param list
	 * @param wrapper
	 * @return JSONArray
	 */
	public static <T> JSONArray listToTree(List<T> list, IListToTreeWrapper<T> wrapper) {
		return listToTree(list, wrapper, 10);
	}
	
	/**
	 * 封装一个列表到树形结构的JSONArray
	 * @param list
	 * @param wrapper
	 * @param level 下标从0开始
	 * @return JSONArray
	 */
	public static <T> JSONArray listToTree(List<T> list, IListToTreeWrapper<T> wrapper, int level) {
		return listToTree(list, wrapper, level, "items");
	}  
	
	public static <T> JSONArray listToTree(List<T> list, IListToTreeWrapper<T> wrapper, int level, String itemsKey) {
		JSONArray array = new JSONArray();
		if(NumberUtils.isNotValid(level) || CollectionUtils.isEmpty(list)) 
			return array;
		list.stream().filter(t -> {
			Object object = wrapper.getParentValue(t);
			return object == null || StringUtils.isBlank(String.valueOf(wrapper.getParentValue(t)));
		}).collect(Collectors.toList()) .forEach(t -> {
			JSONObject json = wrapper.doConvertJson(t);
			
			_listToTreeItem(t, json, list, wrapper, level, 2, itemsKey);
			array.add(json);
		});
		
		return array;
	}
	
	static <T> void _listToTreeItem(T targetT, JSONObject targetJson, List<T> list, IListToTreeWrapper<T> wrapper, int level, int currLevel, String itemsKey) {
		if(currLevel > level) return;
		
		JSONArray array = new JSONArray();
		list.stream().filter(t -> { //挑选出父类ID=targetT.id的集合
			Object object = wrapper.getParentValue(t);
			Object pkValue = wrapper.getPkValue(targetT);
			return ObjectUtils.equals(object, pkValue);
		}).collect(Collectors.toList()).forEach(t -> {
			JSONObject json = wrapper.doConvertJson(t);
			
			_listToTreeItem(t, json, list, wrapper, level, currLevel + 1, itemsKey);
			array.add(json);
		});
		
		if(CollectionUtils.isNotEmpty(array)) {
			targetJson.put(itemsKey, array);
		}
	}
	
	public interface IListToTreeWrapper<T> {
		Object getParentValue(T t);
		Object getPkValue(T t);
		JSONObject doConvertJson(T t);
	}

	@SuppressWarnings("unchecked")
	@Deprecated
	public static <T> T deepGetJSON(String json, String deepKey, T defaultJson) {
		JSONObject jsonObject = parseObject(json);
		
		Object object = __deepGetObject(jsonObject, deepKey);
		if(object == null) return defaultJson;
		else if(object instanceof JSON) {
			return (T) object;
		}
		
		return defaultJson;
	}
	
	public static <T> T deepGet(String json, String deepKey, Class<T> clazz) {
		JSONObject jsonObject = parseObject(json);
		return deepGet(jsonObject, deepKey, clazz);
	}
	
	public static <T> T convert(String json, Class<T> clazz) {
		return deepGet(json, null, clazz);
	}
	
	public static <T> T convert(JSONObject json, Class<T> clazz) {
		return deepGet(json, null, clazz);
	}
	
	@SuppressWarnings("unchecked")
	public static <T> T deepGet(JSONObject json, String deepKey, Class<T> clazz) {
		Object o = __deepGetObject(json, deepKey);
		if(o == null) {
			return null;
		}
		
		if(clazz == null) {
			return (T) o;
		}
		
		T newInstance = null;
		try {
			newInstance = clazz.newInstance();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}
		Assert.notNull(newInstance, clazz.getName() + "无空构造函数");
		return __convert(o, newInstance);
	}
	
	public static <T> T deepGet(String json, String deepKey, T defaultValue) {
		JSONObject jsonObject = parseObject(json);
		return __deepGet(jsonObject, deepKey, defaultValue);
	}
	
	public static <T> T deepGet(JSONObject json, String deepKey, T defaultValue) {
		return __deepGet(json, deepKey, defaultValue);
	}
	
	static Object __deepGetObject(JSONObject json, String deepKey) {
		if(json == null) {
			return null;
		}
		
		if(StringUtils.isBlank(deepKey)) {
			return json;
		}
		
		String[] deep = StringUtils.split(deepKey, ".");
		JSONObject temp = json;
		
		for (int i = 0; i < deep.length; i++) {
			String key = deep[i];
			Object object = temp.get(key);
			
			if(i == deep.length - 1) { //最后一个
				return object;
			}
			
			if(object == null) {
				return null;
			}
			
			if((object instanceof JSONObject)) {//不是json也返回默认值
				temp = (JSONObject) object;
			} else if (object instanceof String){
				temp = parseObject((String) object);
			} else {
				return null;
			}
		}
		
		return null;
	}
	
	static <T> T __deepGet(JSONObject json, String deepKey, T defaultValue) {
		Object o = __deepGetObject(json, deepKey);
		if(o == null) {
			return defaultValue;
		}
		
		return __convert(o, defaultValue);
	}

	@SuppressWarnings("unchecked")
	static <T> T __convert(Object object, T defaultValue) {
		if(object == null) {
			return defaultValue;
		}
		
		try {
			if(defaultValue instanceof JSONObject) {
				return (T) JSON.parseObject(object.toString());
			} else if(defaultValue instanceof JSONArray) {
				return (T) JSON.parseArray(object.toString());
			}
			return (T) TypeUtils.cast(object, defaultValue.getClass(), ParserConfig.getGlobalInstance());
		} catch(Exception e) {
			return (T) JSON.parseObject(object.toString(), defaultValue.getClass());
		}
	}
	
	public static JSONObject parseObject(String ext) {
		JSONObject extJson = null;
		try {
			extJson = JSON.parseObject(ext);
		} catch(Exception e) {
			extJson = new JSONObject();
		}
		
		if(extJson == null) {
			extJson = new JSONObject();
		}
		
		return extJson;
	}
	
	public static void main(String[] args) {
		String ext = "{\"store\":{\"masterIcon\":\"https://qtj-dev.oss-cn-hangzhou.aliyuncs.com/resources/20200611/07d8a5cf7b974339b6cccc317f213811.JPG\",\"storeName\":\"北城之一1\",\"id\":1561,\"contactPhone\":\"\",\"phoneNo\":\"18568238271\"},\"user\":{\"headImg\":\"http://thirdwx.qlogo.cn/mmopen/vi_32/DYAIOgq83eoBset0bCY4atoHBH1ibsc8ia8iaZicIzcxz2hFSlxw0yLmicxsiaH5xia4qQYxXsqMibXicicNtt31ialYh2C5Q/132\",\"phone\":\"18568238271\",\"nickName\":\"巴啦啦能量\",\"id\":862}}";
		
		System.out.println(JsonUtils.deepGet(ext, "store.storeName", ""));
		Object deepGet = JsonUtils.deepGet(ext, "store.storeName", null);
		System.out.println(deepGet);
		Integer deepGet2 = JsonUtils.deepGet(ext, "store.storeName2", null);
		System.out.println(deepGet2);
		Object deepGet3 = JsonUtils.deepGet(ext, "store.storeName2", "");
		System.out.println(deepGet3);
	}
	
}
